package com.hxkj.MQ.Sender.impl;

import com.hxkj.MQ.Sender.GeneratorStaticFileService;
import com.hxkj.MQ.config.MQConstant;
import com.hxkj.dao.ChannelDao;
import com.hxkj.dao.ColumnDao;
import com.hxkj.dao.ManuscriptDao;
import com.hxkj.domain.po.*;
import com.hxkj.service.ArticleService;
import com.hxkj.service.LeafletService;
import com.hxkj.service.TagsService;
import com.hxkj.thread.ThreadPoolManager;
import com.platform.common.domain.result.ResultMessageStruct;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.*;

@Service("generatorStaticFileService")
@Slf4j
public class GeneratorStaticFileServiceImpl implements GeneratorStaticFileService {

    @Autowired
    private ManuscriptDao manuscriptDao;
    @Autowired
    private ThreadPoolManager threadPoolManager;
    @Autowired
    private TagsService tagsService;
    @Autowired
    private ColumnDao columnDao;
    @Autowired
    private ChannelDao channelDao;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private ArticleService articleService;
    @Autowired
    private LeafletService leafletService;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Override
    public ResultMessageStruct GenFile(String params) throws Exception {
        ResultMessageStruct resultMessageStruct = new ResultMessageStruct();
        /**
         * 一个月以内需要生成静态文件的文章记录
         */
        //siteId应该通过定时任务传过来，这里测试展示使用静态值
        Long siteId = Long.valueOf(params);//0L;
        Map<String, Object> map = new HashMap<>();
        map.put("siteId", siteId);
        map.put("updateTime", System.currentTimeMillis() - 24 * 60 * 60 * 1000 * 30L);//设置一个月时间查询参数
        List<Article> alist = manuscriptDao.getPreCreateArticle(map);

        /**
         * 需要生成静态文件的频道
         */
        List<Channel> channelList = manuscriptDao.getPreCreateChannel(map);
        List<Channel> chlist = new ArrayList<>();
        chlist.addAll(channelList);
        for (Channel channel : channelList) {
            if (channel.getTempletId() == null) {
                log.warn("频道相关TemplateId不存在");
                chlist.remove(channel);
            }
            if (channel.getTempletName() == null) {
                log.warn("频道相关TemplateName不存在");
                chlist.remove(channel);
            }

        }


        /**
         * 需要生成静态文件的分类
         */
        List<Column> columnsList = manuscriptDao.getPreCreateColumn(map);
        List<Column> colist = new ArrayList<>();
        colist.addAll(columnsList);
        for (Column column : columnsList) {
            if (column.getTempletId() == null) {
                log.warn("分类相关TemplateId不存在");
                colist.remove(column);
            }
        }

        /**
         * 需要生成的tag详情页
         */
        Tags entity = new Tags();
        entity.setSiteId(siteId);
        List<Tags> listTags = tagsService.getShowTagsList(entity);


        long start = System.currentTimeMillis();
        threadPoolManager.genArticleFiles(alist);
        threadPoolManager.genChannelFiles(chlist);
        threadPoolManager.genColumnFiles(colist);
        threadPoolManager.genTagInfoFiles(listTags);
        log.info("执行总耗时：" + (System.currentTimeMillis() - start));

        resultMessageStruct.setMessage("success");
        resultMessageStruct.setCode(200);
        return resultMessageStruct;
    }

    @Override
    public void GenArticleFile(List<Article> list) throws Exception {
        // 清除所有的自定义标签的redis缓存
        redisTemplate.delete(redisTemplate.keys("directive_*"));
        if (list == null || list.size() == 0) return;
        for (Article article : list) {
            rabbitTemplate.convertAndSend(MQConstant.CMS_EXCHANGE, MQConstant.ARTICLE_ROUTING_KEY, article);
        }
    }

    @Override
    public void GenChannelFile(List<Channel> list) throws Exception {
        // 清除所有的自定义标签的redis缓存
        redisTemplate.delete(redisTemplate.keys("directive_*"));
        if (list == null || list.size() == 0) return;
        for (Channel channel : list) {
            rabbitTemplate.convertAndSend(MQConstant.CMS_EXCHANGE, MQConstant.CHANNEL_ROUTING_KEY, channel);
        }
    }

    @Override
    public void GenColumnFile(List<Column> list) throws Exception {
        if (list == null || list.size() == 0) return;
        int count = 0;
        for (Column column : list) {
            // 生成分类静态前,先清除对应分类在redis中的面包屑缓存
            redisTemplate.delete("breadCrumbs_" + column.getSiteId() + "_" + column.getColumnId());
            if (column.getPageNum() > 0) {
                for (int i = 1; i <= column.getPageNum(); i++) {
                    count++;
                    column.setCount(i);
                    rabbitTemplate.convertAndSend(MQConstant.CMS_EXCHANGE, MQConstant.COLUMN_ROUTING_KEY, column);
                    log.debug("当前分类{}数据量为{}",column.getColumnId(),count);
                }
            }
        }
    }

    /**
     * 生成单页静态页面
     *
     * @param leaflet
     * @throws Exception
     */
    @Override
    @Async
    public void GenLeafletFile(Leaflet leaflet) throws Exception {

        // 清除所有的自定义标签的redis缓存
        redisTemplate.delete(redisTemplate.keys("directive_*"));
        leafletService.getLeafletList(leaflet).getData().parallelStream().forEach(leaflet1 -> {
            try {
                log.debug("发送单页{}生成任务队列", leaflet1.getLeafletId());
                rabbitTemplate.convertAndSend(MQConstant.CMS_EXCHANGE, MQConstant.LEAFLET_ROUTING_KEY, leaflet1);
            } catch (Exception e) {
                log.error("发送单页生成任务队列出错",e);
            }
        });


    }

    @Override
    public void GenTagInfoFile(List<Tags> list) throws Exception {
        if (list == null || list.size() == 0) return;
        // 清除所有的自定义标签的redis缓存
        redisTemplate.delete(redisTemplate.keys("directive_*"));
        for (Tags tags : list) {
            rabbitTemplate.convertAndSend(MQConstant.CMS_EXCHANGE, MQConstant.TAG_INFO_ROUTING_KEY, tags);
        }
    }

    /**
     * 一站生成静态页面
     * 注:未改变旧逻辑,重构新增方法,由router多次调用article服务接口合并到一个接口调用,by yangjianguo
     *
     * @param freeMarker
     * @throws Exception
     */
    @Override
    public void createSiteAll(FreeMarker freeMarker) throws Exception {
        Long start = System.currentTimeMillis();
        Long siteId = freeMarker.getSiteId();
        /**
         * 生成全站文章静态页
         */
        Article article = new Article();
        article.setSiteId(siteId);
        this.generateArticleHTML(article);
        /**
         * 需要生成静态文件的分类
         */
        Column paramColumn = new Column();
        paramColumn.setSiteId(siteId);
        List<Column> columnsList = columnDao.getShowColumnList(paramColumn);
        this.GenColumnFile(columnsList);

        /**
         * 需要生成的tag详情页
         */
        Tags entity = new Tags();
        entity.setSiteId(siteId);
        List<Tags> listTags = tagsService.getShowTagsList(entity);
        this.GenTagInfoFile(listTags);

        /**
         * 生成频道的静态文件
         */
        this.createChannelPages(freeMarker);

        // 生成单页静态
        Leaflet leaflet = new Leaflet();
        leaflet.setSiteId(siteId);
        this.GenLeafletFile(leaflet);

        log.info("执行总耗时：" + (System.currentTimeMillis() - start));
    }

    @Override
    @Async
    public void generateArticleHTML(Article parameterArticle) throws Exception {
        // 清除所有的自定义标签的redis缓存
        redisTemplate.delete(redisTemplate.keys("directive_*"));
        // 30天内的文章
        parameterArticle.setUpdateTime(System.currentTimeMillis() - 24 * 60 * 60 * 1000 * 30L);
        articleService.getArticleListByTime(parameterArticle).parallelStream().forEach(article -> {
            try {
                log.debug("发送文章{}生成任务队列", article.getArticleId());
                rabbitTemplate.convertAndSend(MQConstant.CMS_EXCHANGE, MQConstant.ARTICLE_ROUTING_KEY, article);
            } catch (Exception e) {
                log.error("发送文章生成任务队列出错",e);
            }
        });
    }


    /**
     * 多个频道生成静态页
     *
     * @param freeMarker
     * @return 返回Map对象, key为进度计数器redis key,value为总数
     * @throws Exception
     */
    private Map<String, Integer> createChannelPages(FreeMarker freeMarker) throws Exception {
        redisTemplate.delete(redisTemplate.keys("directive_*"));
        String websocket_key = "WEBSOCKET_KEY_" + UUID.randomUUID();
        List<Channel> list = null;
        //没有传入频道的channelIds ,生成全部频道
        if (StringUtils.isBlank(freeMarker.getChannelIds())) {
            Channel channel = new Channel();
            channel.setSiteId(freeMarker.getSiteId());
            list = channelDao.getListBySiteId(channel);
        } else {
            list = new ArrayList<>();
            for (String channelId : freeMarker.getChannelIds().split(",")) {
                Channel channel = channelDao.getChannelById(Long.valueOf(channelId));
                channel.setSocketKey(websocket_key);
                list.add(channel);
            }
        }
        if (list != null && list.size() != 0) {
            redisTemplate.opsForValue().set(websocket_key, 0);
            this.GenChannelFile(list);
        }
        Map<String, Integer> channelSizeMap = new HashMap<>();
        channelSizeMap.put(websocket_key, list == null ? 0 : list.size());
        return channelSizeMap;
    }
}
